import React, {useEffect} from 'react';
import { useTreeItem } from '@mui/lab/TreeItem'
import { Typography, Checkbox } from '@mui/material'
import { searchDataById } from '@/utils/util'
import { Autorenew, ArrowRight } from '@mui/icons-material';
import clsx from 'clsx';

const CustomContent = React.forwardRef(function CustomContent(props, ref) {
  const {
    keypropety,
    childrenpropety,
    leafproperty,
    classes,
    className,
    label,
    nodeId,
    icon: iconProp,
    expansionIcon,
    displayIcon,
    showchecked,
    treeData,
    checkedNodes,
    checkChange,
    isClickLabelCheck,
    changeExpandOnLabel,
    disabledItem,
    checkStrictly,
    lazy,
    loadDataByNode,
    lazyLoadData,
    isLeaf
  } = props;
  const {
    disabled,
    expanded,
    selected,
    handleExpansion,
    handleSelection,
    preventSelection,
  } = useTreeItem(nodeId);
  const icon = iconProp || expansionIcon || displayIcon;

  const [isLoadingLeaf, setIsLoadingLeaf] = React.useState(false)
  const [isChecked, setIsChecked] = React.useState(false)
  // 是否是半勾选状态
  const [isIndeterminate, setIsIndeterminate] = React.useState(false)

  /**
   * 
   * @param {Object} nodeInTree 
   * @returns 该节点的子节点数组
   * @desc 懒加载的情况下，点击展开数组的时候需要去获取子节点，必须通过resolve返回数据
   */
  const getChildrenNodes = (nodeInTree) => {
    return new Promise((resolve, reject) => {
      loadDataByNode(nodeInTree, resolve, reject)
    })
  }

  const handleMouseDown = (event) => {
    preventSelection(event);
    if (changeExpandOnLabel && (!isClickLabelCheck || !showchecked)) {
      handleExpansionClick(event)
    }
  };

  const handleExpansionClick = async (event) => {
    try {
      // 在展开的时候判断是不是懒加载，如果是懒加载的话就要去获取数据了
      const nodeInTree = searchDataById(nodeId, treeData, keypropety, childrenpropety)
      if (lazy && !nodeInTree.isLeaf && !nodeInTree[childrenpropety] && !expanded && !isLoadingLeaf) { // 如果该node既不是子节点并且该节点还没有孩子，说明该node还没有加载过子节点
        setIsLoadingLeaf(true)
        const childrenNodes = await getChildrenNodes(nodeInTree)
        if (childrenNodes) { // 如果该节点有子节点，则给子节点
          nodeInTree[childrenpropety] = childrenNodes
          if (isChecked) { // 如果是勾选状态，则将子节点也要勾选
            checkChange(nodeInTree, true)
          }
        } else { // 如果该节点没有子节点，则说明该节点是叶子节点
          nodeInTree[leafproperty] = true
        }
        lazyLoadData(nodeId)
        setIsLoadingLeaf(false)
      }
      handleExpansion(event);
    } catch (err) {
      console.log(err)
      setIsLoadingLeaf(false)
    }
  };

  const handleSelectionClick = (event) => {
    if (disabledItem || disabled) {
      return
    }
    handleSelection(event);
    if (isClickLabelCheck && showchecked) { // 如果点击label的是否需要勾选并且显示了勾选框，则进行勾选框的变化
      thisCheckChange(event, !isChecked)
    }
  };

  useEffect(() => {
    let isChecked = false
    let isIndeterminate = false
    const nodeInSelect = searchDataById(nodeId, checkedNodes, keypropety, childrenpropety)
    if (checkStrictly) { // 如果严格执行了父子不相关, 则表明只需要在数组的第一层判断有没有id，有的话就说明是勾选了，没有的话就说明没有勾选
      const nodeIndex = checkedNodes.findIndex(item => {
        return item[keypropety] === nodeId
      })
      if (nodeIndex >= 0) {
        isChecked = true
      }
    } else {
      if (nodeInSelect && (!nodeInSelect[childrenpropety] || !nodeInSelect[childrenpropety].length)) { // 如果在已选数组里找到并且该数据没有孩子，则就是选中状态
        isChecked = true
      } else if (nodeInSelect && nodeInSelect[childrenpropety] && nodeInSelect[childrenpropety].length) {
        const nodeInTree = searchDataById(nodeId, treeData, keypropety, childrenpropety)
        if (nodeInTree && nodeInTree[childrenpropety] && nodeInTree[childrenpropety].length) { // 如果在数据在树组件数据里并且其有孩子
          if (nodeInTree[childrenpropety].length === nodeInSelect[childrenpropety].length) { // 如果选中的孩子数量与树组件里孩子的数量全部相等 说明孩子已经全部勾选了
            isChecked = true
          } else {
            isIndeterminate = true
          }
        }
      }
    }
    setIsChecked(isChecked)
    setIsIndeterminate(isIndeterminate)
  }, [treeData, checkedNodes, nodeId, checkStrictly, keypropety, childrenpropety])

  // 某一行点击了勾选框，组件内的勾选事件
  const thisCheckChange = (event, checked) => {
    event.stopPropagation();
    const nodeData = searchDataById(nodeId, treeData, keypropety, childrenpropety)
    checkChange(nodeData, checked)
  }

  return (
    <div
      className={clsx(className, classes.root, {
        [classes.expanded]: expanded,
        [classes.selected]: selected,
        [classes.disabled]: disabled,
      })}
      onMouseDown={handleMouseDown}
      ref={ref}
    >
      {
        lazy ? (
          isLoadingLeaf ? (
            <div onMouseDown={(e) => e.stopPropagation()} className={classes.iconContainer} style={{marginRight: '4px'}}>
              <Autorenew className='rotateAni360' style={{ fontSize: 24 }}/>
            </div>
          ) : (
            !isLeaf ? (
              <div onMouseDown={(e) => e.stopPropagation()} onClick={handleExpansionClick} className={classes.iconContainer} style={{marginRight: '4px'}}>
                <ArrowRight className={`${expanded ? 'rotate90' : 'rotate0'} rotateTransition`} style={{ fontSize: 24 }}/>
              </div>
            ) : (
              <div onMouseDown={(e) => e.stopPropagation()} onClick={handleExpansionClick} className={classes.iconContainer} style={{marginRight: '4px'}}>
                {icon}
              </div>
            )
          )
        ) : (
          <div onMouseDown={(e) => e.stopPropagation()} onClick={handleExpansionClick} className={classes.iconContainer} style={{marginRight: '4px'}}>
            {icon}
          </div>
        )
      }
      {
        showchecked && (
          <div onMouseDown={(e) => e.stopPropagation()}>
            <Checkbox size="small" checked={isChecked} indeterminate={isIndeterminate} onChange={(event) => thisCheckChange(event, !isChecked)} disabled={disabledItem || disabled} />
          </div>
        )
      }
      <Typography
        onClick={handleSelectionClick}
        component="div"
        className={classes.label}
        style={{lineHeight: '36px', opacity: disabledItem ? '0.38' : '1', whiteSpace: 'nowrap'}}
      >
        {label}
      </Typography>
    </div>
  );
});

export default CustomContent